#include <jni.h>
#include <string>
#include <unistd.h>
#include <pthread.h>

#include <android/log.h>
#ifndef LOGI(x...)
#define LOGI(x...) __android_log_print(ANDROID_LOG_INFO,"xdag",x)
#endif

pthread_t tid;
pthread_mutex_t g_mutex;
pthread_mutex_t g_clean_mutex;
pthread_cond_t g_clean_cond;
int run_times = 0;
bool is_stoped = true;

void thread_clean(void*arg){

    pthread_mutex_unlock(&g_mutex);
    pthread_mutex_lock(&g_clean_mutex);

    LOGI("clean up called ");
    sleep(5);
    LOGI("signal thread clean ");
    pthread_cond_signal(&g_clean_cond);
    LOGI("signal thread clean over ");
    pthread_mutex_unlock(&g_clean_mutex);
}

void *thread_run(void* arg){
    is_stoped = false;
    pthread_cleanup_push(thread_clean,NULL);
    while(run_times < 0xffffffff){
        pthread_mutex_lock(&g_mutex);
        if(is_stoped)
            pthread_exit((void*)NULL);
        LOGI(" run for the %d times \n",run_times++);
        pthread_mutex_unlock(&g_mutex);
        sleep(1);
    }
    pthread_cleanup_pop(0);
}

extern "C"
JNIEXPORT jstring
JNICALL Java_example_bill_com_pthreadndk_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {

    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jint
JNICALL Java_example_bill_com_pthreadndk_MainActivity_startPthread(
        JNIEnv *env,
        jobject /* this */) {

    pthread_mutex_init(&g_mutex,NULL);
    pthread_mutex_init(&g_clean_mutex,NULL);
    pthread_cond_init(&g_clean_cond,NULL);

    pthread_create(&tid,NULL,thread_run,NULL);
    pthread_detach(tid);

    return 0;
}

extern "C"
JNIEXPORT jint
JNICALL Java_example_bill_com_pthreadndk_MainActivity_stopPthread(
        JNIEnv *env,
        jobject /* this */) {

    pthread_mutex_lock(&g_clean_mutex);

    is_stoped = true;
    LOGI("wait thread clean");

    pthread_cond_wait(&g_clean_cond,&g_clean_mutex);

    LOGI("wait thread clean over ");
    pthread_mutex_unlock(&g_clean_mutex);

    //destory the mutex and condition
    pthread_mutex_destroy(&g_mutex);
    pthread_mutex_destroy(&g_clean_mutex);
    pthread_cond_destroy(&g_clean_cond);

    return 0;
}

extern "C"
JNIEXPORT jint
JNICALL Java_example_bill_com_pthreadndk_MainActivity_killSig(
        JNIEnv *env,
        jobject /* this */) {

    //

    return 0;
}